using System.Collections;
using System.Collections.Generic;
using Cfg;
using UnityEditor.Animations;
using UnityEngine;
using Vector3 = UnityEngine.Vector3;

public class PlayerJumpingState : PlayerAirborneState
{
    private bool isKeepRotating;
    private PlayerRotationData rotationData;
    private bool canStartFall;

    public PlayerJumpingState(PlayerMovementMachine stateMachine) : base(stateMachine)
    {
        rotationData = airborneData.JumpData.RotationData;
    }

#region IState Methods
    public override void Enter()
    {
        base.Enter();
        StateMachine.ReusableData.MovementSpeedModify = 0;
        StateMachine.ReusableData.RotationData = rotationData;
        if (StateMachine.ReusableData.InputMovement != Vector2.zero)
        {
            isKeepRotating = true;
        }

        StateMachine.ReusableData.DecelerationForce =
            StateMachine.Player.Data.PlayerAirborneData.JumpData.DelecerationForce;
        Jump();
    }

    public override void Update()
    {
        base.Update();

        if (!canStartFall && IsMovingUp())
        {
            canStartFall = true;
        }
        
        if (!canStartFall || GetVerticalPlayerVelocity().y > 0)
            return;
        
        StateMachine.ChangeState(StateMachine.FallingState);
    }

    public override void PhysicUpdate()
    {
        base.PhysicUpdate();
        if (isKeepRotating)
        {
            RotateTowardsTargetRotation();
        }

        if (IsMovingUp())
        {
            DecelerateVertically();
        }
    }

    public override void Exit()
    {
        base.Exit();
        isKeepRotating = false;
        SetBaseRotation();
        canStartFall = false;
    }
#endregion

#region Main Methods
    private void Jump()
    {
        Vector3 jumpForce = StateMachine.ReusableData.CurrentJumpForce;
        Vector3 jumpDir = StateMachine.Player.transform.forward;
        if (isKeepRotating)
        {
            jumpDir = GetTargetRotationDirection(StateMachine.ReusableData.CurrentTargetRotation.y);
        }

        jumpForce.x *= jumpDir.x;
        jumpForce.z *= jumpDir.z;

        Vector3 capsuleColliderCenterInWorld =
            StateMachine.Player.ColliderUtility.CapsuleColliderData.Collider.bounds.center;
        Ray capsuleCenterToGroundRay = new Ray(capsuleColliderCenterInWorld, Vector3.down);
        if (Physics.Raycast(capsuleCenterToGroundRay, out RaycastHit hit,
                airborneData.JumpData.JumpToGroundDistance, StateMachine.Player.PlayerLayerData.GroundLayer,
                QueryTriggerInteraction.Ignore))
        {
            float angle = Vector3.Angle(hit.normal, -capsuleCenterToGroundRay.direction);
            if (IsMovingUp())
            {
                float forceModify = StateMachine.Player.Data.PlayerAirborneData.JumpData.JumpForceModifierOnSlopeUpward
                    .Evaluate(angle);
                jumpForce.x *= forceModify;
                jumpForce.z *= forceModify;
            }

            if (IsMovingDown())
            {
                float forceModify = StateMachine.Player.Data.PlayerAirborneData.JumpData
                    .JumpForceModifierOnSlopeDownward.Evaluate(angle);
                jumpForce.y *= forceModify;
            }
        }

        ResetVelocity();
        StateMachine.Player.Rigidbody.AddForce(jumpForce, ForceMode.VelocityChange);
    }
#endregion

#region Reusable Methods
    protected override void ResetSprintState()
    {
    }
#endregion
}